package com.browsesoft.baseadapter;

import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.aote.component.format.FormatFactory;
import com.aote.entity.EntityType;
import com.aote.entity.EntityTypeFactory;
import com.aote.util.StringHelper;
import com.browsesoft.Entity;
import com.browsesoft.EntityManager;
import com.browsesoft.ExtendElement;
import com.browsesoft.Tools;
import com.browsesoft.dbtools.DBTools;
import com.browsesoft.htmlcomponent.HTMLBasicComponent;
import com.browsesoft.htmlcomponent.HTMLLazyTable;
import com.browsesoft.oa.BSHttpServletRequest;
import com.browsesoft.tools.XMLTool;

/**
 * 以延迟加载的方式处理数据，每次以分页方式查找数据
 */
public class HTMLLazyTableModel extends HTMLBasicTableModelAdapter implements
		HTMLLazyTable, AddupModel, SumModel, PrintAbleTableModel {
	/**
	 * 过滤条件
	 */
	String filterCondition = null;

	/**
	 * 本页开始行号
	 */

	private int start;

	/**
	 * 总行数
	 */
	private int rowCount;

	/**
	 * 要汇总的字段名
	 */
	protected LinkedList sumnames;

	/**
	 * 总数据个数及要汇总的字段的结果
	 */
	protected double[] sums;

	/**
	 * 动作参数
	 */
	public String action = "";

	/**
	 * 所选择的打印项列表
	 */
	public LinkedList print;

	/**
	 * 小计合计缓存，
	 */
	private LinkedList addUpSum = new LinkedList();

	/**
	 * 合计总计缓存
	 */
	private LinkedList totalSum = new LinkedList();

	/**
	 * 设置传递的参数
	 * 
	 * @param request
	 *            请求
	 * @param response
	 *            响应
	 * @throws Exception
	 */
	public void service(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		super.service(request, response);
		// 得到action的值
		this.action = request.getParameter("action");
		// 得到选择结果
		String result = request.getParameter("resultdarpent" + "_"
				+ this.component.getName());
		print = Tools.stringToLinkedList(result);
		this.alterfiltercondition(request);
	}

	public void init(HttpServletRequest request) throws Exception {
		super.init(request);
		// 用实际参数值替换过滤条件中的“＃XX＃”
		this.alterfiltercondition(request);
	}

	/**
	 * 用实际参数值替换过滤条件中的“＃XX＃”
	 * 
	 * @param request,HttpServletRequest请求
	 */
	private void alterfiltercondition(HttpServletRequest request) {
		// 得到过滤条件
		filterCondition = this.component.getElement().getAttribute(
				"SQLCondition");
		BSHttpServletRequest brequest = (BSHttpServletRequest) request;
		filterCondition = StringHelper.replaceStr(brequest.getParameters(),
				filterCondition);
	}

	/**
	 * 更新页面元素
	 * 
	 * @throws Exception
	 */
	public void updatePageElement(HTMLBasicComponent htmlBasicComponent)
			throws Exception {
		if (action != null && action.equals("print")) {
			// 打开页面打印模板
			Element e = (Element) this.component.getPage().getDocument()
					.getElementsByTagName("body").item(0);
			e.setAttribute("onload",
					"openMaxWindow('page.jsp?templatename=页面打印模板&amp;compid="
							+ this.component.getName() + "');");
		}
	}

	// 得到要排序的字段
	private String getOrder() {
		String st = "";
		String[] orders = new String[10];
		int max = 0;
		// 从组件中得到所有要处理的元素
		// 得到所有排序元素
		List elems = ExtendElement.findHasAttributeElems("order",
				this.formElement);
		Iterator iter = elems.iterator();
		while (iter.hasNext()) {
			// 得到元素
			Element e = (Element) iter.next();
			// 得到排序顺序
			String order = e.getAttribute("order");
			// 如果元素有order属性
			if (order != null && !order.equals("")) {
				// 得到是否是逆序
				String de = e.getAttribute("desc");
				// 把order转化成整型
				int in = Integer.parseInt(order);
				// 如果是逆序
				if (de != null && !de.equals("")) {
					// 加入desc
					orders[in] = e.getAttribute("name") + " " + "desc";
				}
				// 否则
				else {
					orders[in] = e.getAttribute("name");
				}
				// 如果得到的order值大于max的值
				if (in > max) {
					max = in;
				}
			}
		}
		// 把得到的字段合并成字符串形式
		for (int i = 1; i < max; i++) {
			st += orders[i] + ",";
		}
		// 如果是最后一项
		st += orders[max];
		return st;
	}

	/**
	 * 得到行数
	 * 
	 * @return 行数
	 */
	public int getRowCount() {
		return this.rowCount;
	}

	/**
	 * 得到所有要汇总的列名
	 * 
	 * @return 列名列表
	 */
	public Collection getColNamesOfSum() {
		Collection result = new LinkedList();
		Iterator it = this.elements.iterator();
		// 对于每一个
		while (it.hasNext()) {
			Element item = (Element) it.next();
			String temp = item.getAttribute("addup");
			// 如果该列要汇总
			if (temp != null && !temp.equals("")) {
				// 将列名加入列表
				result.add(item.getAttribute("name"));
			}
		}
		return result;
	}

	/**
	 * 内部得到行数的方法
	 * 
	 * @return 行数
	 */
	protected int getRowCountInner() {
		try {
			// 得到查询条件
			String condition = this.getAllCondition();
			// 查找页面上的load标志
			String load = this.component.getElement().getAttribute("load");
			// 如果没有查许条件并且有load标志
			if (load != null && load.equals("load") && condition.equals("")) {
				// 返回0行
				return 0;
			} else {
				this.sumnames = (LinkedList) this.getColNamesOfSum();
				this.sums = EntityManager.getInstance().getEntityCountAndSums(
						this.entityType, condition, this.sumnames);
				return (int) this.sums[0];
			}
		} catch (Exception ex) {
			return 0;
		}
	}

	/**
	 * 得到一行数据
	 * 
	 * @param row
	 *            行号
	 */
	public Entity getOneRow(int row) {
		return (Entity) datas.get(row - start);
	}

	/**
	 * 根据页面需要加载数据
	 * 
	 * @param start
	 *            该页表格的起始行
	 * @param end
	 *            该页表格的结束行
	 */
	public void loadData(int start, int end) {
		// 重新得到行数
		this.rowCount = this.getRowCountInner();
		// 得到查询条件
		String condition = this.getAllCondition();
		// 查找页面上的load标志
		String load = this.component.getElement().getAttribute("load");
		// 如果没有查许条件并且有load标志
		if (load != null && load.equals("load") && condition.equals("")) {
			// 不加载数据
			return;
		} else {
			this.datas = (LinkedList) EntityManager.getInstance().getEntities(
					this.entityType, start, end, condition, this.getOrder());
			this.start = start;
		}
	}

	/**
	 * 得到所选择的要打印的列表
	 */
	public LinkedList getPrintList() {
		return this.print;
	}

	/**
	 * 得到条件
	 * 
	 * @return
	 */
	protected String getAllCondition() {
		// 得到查询条件
		String searchCondition = hashtableToSQLCondition();
		// 连接查询条件和过滤条件
		return DBTools.connectCondition(searchCondition, filterCondition);
	}

	public String hashtableToSQLCondition() {
		Hashtable dateConds = new Hashtable();
		String result = "";
		// 对于每一个条件
		Iterator iter = this.condition.keySet().iterator();
		while (iter.hasNext()) {
			// 得到名字和值
			String name = (String) iter.next();
			String value = (String) this.condition.get(name);
			if (name.indexOf("_start") != -1 || name.indexOf("_end") != -1) {
				dateConds.put(name, value);
				continue;
			}
			String con = name + "='" + value + "'";
			// 处理逻辑运算符
			value = processLogic(name, value, "and");
			value = processLogic(name, value, "or");
			// 关键字处理
			name = DBTools.getSQLStatement().DBKeyDispose(name);
			// 如果包含条件运算符
			if (value.indexOf('>') != -1 || value.indexOf(">=") != -1
					|| value.indexOf('<') != -1 || value.indexOf("<=") != -1) {
				con = name + value;
			}
			// 如果是模糊查询
			else if (true) {
				con = name + " like '" + value + "'";
			}
			// 添加一个条件
			result = DBTools.connectCondition(result, con, "and");
		}
		// 处理日期条件
		if (!dateConds.isEmpty()) {
			String dateName = "";
			String startDate = "";
			String endDate = "";
			Iterator iterDate = dateConds.keySet().iterator();
			while (iterDate.hasNext()) {
				String name = (String) iterDate.next();
				if (name.indexOf("_start") != -1) {
					dateName = name.substring(0, name.length() - 6);
					startDate = (String) dateConds.get(name);
				} else if (name.indexOf("_end") != -1) {
					dateName = name.substring(0, name.length() - 4);
					endDate = (String) dateConds.get(name);
				}
			}
			// 如果只有一个日期条件
			String cond = "";
			if (startDate.equals("")) {
				cond += "  " + dateName + " like '" + endDate + "%'";
			} else if (endDate.equals("")) {
				cond += " " + dateName + " like '" + startDate + "%'";
			} else {
				cond += " " + dateName + " >= '" + startDate + "' and "
						+ dateName + " <= '" + endDate + "%'";
			}
			if (result.equals("")) {
				result = cond;
			} else if (result.endsWith("and")) {
				result += cond;
			} else {
				result += " and " + cond;
			}
		}
		return result;
	}

	private static String processLogic(String name, String value, String logic) {
		StringBuffer result = new StringBuffer(value);
		// 对于每一个逻辑运算符
		int pos = result.indexOf(logic);
		while (pos != -1) {
			result.insert(pos + logic.length() + 1, name);
			pos = result.indexOf(logic, pos + logic.length() + 1);
		}
		return result.toString();
	}

	/**
	 * 换OnClick内容,在原来基础上换entityType值
	 * 
	 * @param entity
	 *            对应的实体
	 * @param onClick
	 *            onClick属性值
	 * @return
	 */
	protected String replaceOnClick(Entity entity, String onClick) {
		String result = super.replaceOnClick(entity, onClick);
		// 得到实体类型
		String typeName = (String) entity.getAttributes().get("entitytype");
		// 替换实体类型
		result = result.replaceAll("#entitytype#", typeName);
		// 得到表名
		EntityType entityType = EntityTypeFactory.getInstance().getEntityType(
				typeName);
		String tableName = entityType.getTableName();
		// 返回替换表名后的结果
		return result.replaceAll("#tablename#", tableName);
	}

	/**
	 * 小计
	 * 
	 * @param td
	 *            要修改的单元格
	 * @param doc
	 *            页面所对应的文档
	 * @param col
	 *            要修改的列号
	 */
	public void modifyAddupCell(Document doc, Element td, int col)
			throws Exception {
		// 创建小计默认文本
		String str = this.getStringAddup(col);
		Node node = XMLTool.createTextNode(doc, str);
		// 替换单元格
		ExtendElement.replaceElementContext(td, node);
	}

	/**
	 * 得到某列小计的字符串结果
	 */
	private String getStringAddup(int col) {
		// 如果大于最后的数据列并且有小计合计数据
		if (col > this.TDPosition.y && this.addUpSum.size() > 0) {
			String sum = getAddUpSum();
			this.addUpSum.clear();
			return sum;
		}
		// 不是数据列，不计算
		if (col < this.TDPosition.x || col > this.TDPosition.y) {
			return " ";
		}
		// 创建小计默认文本
		String result = " ";
		col = col - this.TDPosition.x;
		Element element = (Element) this.elements.get(col);
		String addup = (String) element.getAttribute("addup");
		// 如果某一列需要小计
		if (addup != null && !addup.equals("")) {
			// 创建要替换的结点，结点信息为该列的小计
			result = this.getAddup(col, element);
		}
		// 如果需要小计合计
		if (element.hasAttribute("addupsum")) {
			this.addUpSum.add(result);
		}
		return result;
	}

	private String getAddUpSum() {
		double num = 0.00;
		Iterator iter = this.addUpSum.iterator();
		while (iter.hasNext()) {
			String str = (String) iter.next();
			num = Double.parseDouble(str) + num;
		}
		return num + "";
	}

	private String getTotalSum() {
		double num = 0.00;
		Iterator iter = this.totalSum.iterator();
		while (iter.hasNext()) {
			String str = (String) iter.next();
			num = Double.parseDouble(str) + num;
		}
		return num + "";
	}

	/**
	 * 得到某列小计值
	 * 
	 * @param col,列号
	 */
	private String getAddup(int col, Element elem) {
		// 取得实体
		Iterator iter = this.datas.iterator();
		double sum = 0;
		// 对于每一个
		while (iter.hasNext()) {
			Entity item = (Entity) iter.next();
			// 从实体取出需要小计的列名
			Object name = this.enames.get(col);
			try {
				// 将该列的值累加
				sum += Double.parseDouble((String) item.getAttributes().get(
						name));
			} catch (Exception e) {
			}
		}
		String str = FormatFactory.getInstance().format(sum + "", elem);
		return str;
	}

	/**
	 * 修改要打印内容的单元格
	 * 
	 * @param td
	 *            要修改的单元格
	 * @param doc
	 *            页面所对应的文档
	 * @param col
	 *            列号
	 * @param row
	 *            行号
	 */
	public void modifyPrintCell(Document doc, Element td, int row, int col) {
	}

	/**
	 * 总计
	 * 
	 * @param td
	 *            要修改的单元格
	 * @param doc
	 *            页面所对应的文档
	 * @param col
	 *            列号
	 */
	public void modifySumCell(Document doc, Element td, int col)
			throws Exception {
		String str = this.getSum(col);
		Node node = XMLTool.createTextNode(doc, str);
		// 替换单元格
		ExtendElement.replaceElementContext(td, node);
	}

	/**
	 * 得到某列总计值
	 * 
	 * @param col,列号
	 */
	private String getSum(int col) {
		// 如果大于最后的数据列并且有小计合计数据
		if (col > this.TDPosition.y && this.totalSum.size() > 0) {
			String sum = getTotalSum();
			this.totalSum.clear();
			return sum;
		}
		// 不是数据列，返回空
		if (col < this.TDPosition.x || col > this.TDPosition.y) {
			return " ";
		}
		try {
			String result = " ";
			col = col - this.TDPosition.x;
			Element element = (Element) this.elements.get(col);
			String addup = (String) element.getAttribute("addup");
			// 如果某一列需要总计
			if (addup != null && !addup.equals("")) {
				// 得到列名
				String name = (String) this.enames.get(col);
				// 得到该列所对应的汇总数据的序号
				int num = this.sumnames.indexOf(name);
				double d = this.sums[num + 1];
				// 创建要替换的结点，结点信息为该列的总计
				result = FormatFactory.getInstance().format(d + "", element);
			}
			// 如果需要小计合计
			if (element.hasAttribute("addupsum")) {
				this.totalSum.add(result);
			}
			return result;
		} catch (Exception ex) {
			return "0.0";
		}
	}

	/**
	 * 根据列名得到总计
	 */
	public String getSumByColName(String colName) {
		int num = this.sumnames.indexOf(colName);
		double d = this.sums[num + 1];
		String str = String.valueOf(d);
		return str;
	}
}